package com.etoak.stock.service.impl;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.system.UserInfo;
import com.etoak.stock.constant.StockConstant;
import com.etoak.stock.mapper.SysRoleMapper;
import com.etoak.stock.mapper.SysUserRoleMapper;
import com.etoak.stock.pojo.domin.SysAddUserDomain;
import com.etoak.stock.pojo.domin.SysUserDomain;
import com.etoak.stock.pojo.entity.SysRole;
import com.etoak.stock.pojo.entity.SysUserRole;
import com.etoak.stock.service.UserService;
import com.etoak.stock.mapper.SysUserMapper;
import com.etoak.stock.pojo.entity.SysUser;
import com.etoak.stock.utils.IdWorker;
import com.etoak.stock.vo.req.LoginReqVo;
import com.etoak.stock.vo.req.UpdateUserRoleVo;
import com.etoak.stock.vo.req.UpdateUserVo;
import com.etoak.stock.vo.req.UserPageReqVo;
import com.etoak.stock.vo.resp.*;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.awt.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;


@Service
@Slf4j
public class UserServiceImpl implements UserService {
    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;

    @Autowired
    private SysRoleMapper sysRoleMapper;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public SysUser finUserInfoByUserName(String username) {
        return sysUserMapper.finUserInfoByUserName(username);
    }

    //用户登录
    @Override
    public R<LoginRespVo> login(LoginReqVo loginReqVo) {
        //1.判断输入的参数是合法
        if (loginReqVo == null || StringUtils.isBlank(loginReqVo.getUsername()) || StringUtils.isBlank(loginReqVo.getPassword())) {
            return R.error(ResponseCode.DATA_ERROR);
        }

        //判断验证输入的验证码是否存在
        if (StringUtils.isBlank(loginReqVo.getCode()) || StringUtils.isBlank(loginReqVo.getSessionId())) {
            return R.error(ResponseCode.CHECK_CODE_ERROR);
        }
        //判断redis保存的验证码和输入的验证码是否相同 （比较时忽略大小写）
        String redisCode = (String) redisTemplate.opsForValue().get(StockConstant.CHECK_PREFIX + loginReqVo.getSessionId());
        if (StringUtils.isBlank(redisCode)) {
            return R.error(ResponseCode.CHECK_CODE_TIMEOUT);
        }

        if (!redisCode.equals(loginReqVo.getCode())) {
            return R.error(ResponseCode.CHECK_CODE_ERROR);
        }
        redisTemplate.delete("CK:" + loginReqVo.getSessionId());

        //2.根据用户名去数据库获取用户明的密文
        SysUser sysUser = sysUserMapper.finUserInfoByUserName(loginReqVo.getUsername());
        if (sysUser == null) {
            return R.error(ResponseCode.ACCOUNT_NOT_EXISTS);
        }

        //3.调佣密文取配器  输入的密码和数据库的密文是否取配
        if (!passwordEncoder.matches(loginReqVo.getPassword(), sysUser.getPassword())) {
            return R.error(ResponseCode.USERNAME_OR_PASSWORD_ERROR);
        }
        //4.响应
        LoginRespVo loginRespVo = new LoginRespVo();
        BeanUtils.copyProperties(sysUser, loginRespVo);
        return R.ok(loginRespVo);
    }

    //声明验证码
    @Override
    public R<Map> getCaptchaCode() {
        //1.声明图片的验证码
        /*  参数1：图片的width
            参数2：图片的高度
            参数3:图片中包含验证码的长度
            参数4：a干扰线的数量
        * */
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(250, 40, 4, 5);
        //声明背景颜色
        lineCaptcha.setBackground(Color.LIGHT_GRAY);
        //获得校验码
        String code = lineCaptcha.getCode();
        //获取经过base6编码处理的图片数据
        String imageBase64 = lineCaptcha.getImageBase64();
        //2.生成sessionId
        String sessionId = String.valueOf(idWorker.nextId());
        log.info("图片生成图片校验码：{}", code, sessionId);
        //3.将sessionId作为key 校验码保存redis中
        redisTemplate.opsForValue().set(StockConstant.CHECK_PREFIX + sessionId, code, 5, TimeUnit.MINUTES);
        Map<String, String> hashMap = new HashMap();
        hashMap.put("imageData", imageBase64);
        hashMap.put("sessionId", sessionId);
        return R.ok(hashMap);
    }

    /*
     * @author 孙有泽
     * @date 2024/10/24 14:27
     * @description 多条件综合查询用户分页信息，条件包含：分页信息 用户创建日期范围
     */
    @Override
    public R<PageResult<SysUserDomain>> getUsers(UserPageReqVo userPageReqVo) {

        PageHelper.startPage(userPageReqVo.getPageNum(), userPageReqVo.getPageSize());
        List<SysUserDomain> users = sysUserMapper.getUsers(userPageReqVo.getUserName(), userPageReqVo.getNickName(), userPageReqVo.getStartTime(), userPageReqVo.getEndTime());
        if (CollectionUtil.isEmpty(users)) {
            return R.error(ResponseCode.NO_RESPONSE_DATA.getMessage());
        }
        PageInfo<SysUserDomain> sysUserDomainPageInfo = new PageInfo<>(users);
        PageResult pageResult = new PageResult(sysUserDomainPageInfo);
        return R.ok(pageResult);
    }

    /*
     * @author 孙有泽
     * @date 2024/10/24 14:27
     * @description 添加用户信息
     */
    @Override
    public R addUser(SysAddUserDomain sxysAddUserDomain) {
        SysUser sysUser = sysUserMapper.finUserInfoByUserName(sxysAddUserDomain.getUsername());
        if (sysUser != null) {
            R.error(ResponseCode.ACCOUNT_EXISTS_ERROR);
        }
        SysUser user = new SysUser();
        BeanUtils.copyProperties(sxysAddUserDomain, user);
        user.setId(idWorker.nextId());
        int i = sysUserMapper.addUser(user);
        if (i > 0) {
            return R.ok(ResponseCode.SUCCESS);
        } else {
            return R.error(ResponseCode.ERROR.getMessage());
        }
    }

    /*
     * @author 孙有泽
     * @date 2024/10/24 16:40
     * @description 获取用户具有的角色信息，以及所有角色信息
     */
    @Override
    public R<Map<String, List>> getUserRoles(String userId) {
        List<String> ownRoleIds = sysUserRoleMapper.getUserRolesById(userId);
        List<SysRole> allRole = sysRoleMapper.getAllRoles();
        Map<String, List> map = new HashMap<>();
        map.put("ownRoleIds", ownRoleIds);
        map.put("allRole", allRole);
        return R.ok(map);
    }

    @Override
    public R updateUserRole(UpdateUserRoleVo updateUserRoleVo) {
        List<String> ownRoleIds = sysUserRoleMapper.getUserRolesById(updateUserRoleVo.getUserId());
        if (!CollectionUtil.isEmpty(ownRoleIds)) {
            int i = sysUserRoleMapper.deleteUserRole(updateUserRoleVo.getUserId());
            if (i < 0) {
                return R.error(ResponseCode.NO_RESPONSE_DATA);
            }
        }
        ArrayList<SysUserRole> SysUserRoles = new ArrayList<>();
        for (Long roleId : updateUserRoleVo.getRoleIds()) {
            SysUserRoles.add(SysUserRole.builder().id(idWorker.nextId()).userId(Long.valueOf(updateUserRoleVo.getUserId())).roleId(roleId).build());
        }
        int j = sysUserRoleMapper.updateUserRole(SysUserRoles);
        if (j > 0) {
            return R.ok(ResponseCode.SUCCESS);
        } else {
            return R.error(ResponseCode.ERROR.getMessage());
        }
    }

    @Override
    public R<UserInfoResp> getUserById(String userId) {
        SysUser sysUser = sysUserMapper.getUserById(Long.valueOf(userId));
        if (sysUser != null) {
            UserInfoResp userInfoResp = new UserInfoResp();
            BeanUtils.copyProperties(sysUser, userInfoResp);
            return R.ok(userInfoResp);
        } else {
            return R.error(ResponseCode.NO_RESPONSE_DATA);
        }

    }

    @Override
    public R updateUser(UpdateUserVo updateUserVo) {
        SysUser sysUser = sysUserMapper.getUserById(updateUserVo.getId());
        if (sysUser != null) {
            BeanUtils.copyProperties(updateUserVo, sysUser);
            int i = sysUserMapper.updateUser(sysUser);
            if (i > 0) {
                R.ok();
            } else {
                R.error(ResponseCode.ERROR);
            }
        }
        return R.error(ResponseCode.NO_RESPONSE_DATA);


    }

    @Override
    public R deleteBatchUser(List<Long> ids) {
        int i = sysUserMapper.deleteBatchUser(ids);
        if (i > 0) {
            return R.ok();
        } else {
            return R.error(ResponseCode.ERROR.getMessage());
        }

    }

}
